using Microsoft.EntityFrameworkCore;
using System.Text.Json;
using JGSY.CMS.LowCode.Platform.Domain.Entities;
using JGSY.CMS.LowCode.Platform.Domain.Interfaces;
using JGSY.CMS.LowCode.Platform.Infrastructure.CmsDbContext;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Repositories
{
    public class ContentRepository : IContentRepository
    {
        private readonly LowCodeDbContext _context;

        public ContentRepository(LowCodeDbContext context)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context));
        }

        public async Task<IEnumerable<ContentModel>> GetAllModelsAsync()
        {
            return await _context.ContentModels.OrderBy(m => m.Name).ToListAsync();
        }

        public async Task<ContentModel?> GetModelByIdAsync(long id)
        {
            return await _context.ContentModels.FirstOrDefaultAsync(m => m.Id == id);
        }

        public async Task CreateModelAsync(ContentModel model)
        {
            if (model == null) throw new ArgumentNullException(nameof(model));
            
            model.CreatedAt = DateTime.UtcNow;
            model.UpdatedAt = DateTime.UtcNow;
            
            _context.ContentModels.Add(model);
            await _context.SaveChangesAsync();
        }

        public async Task UpdateModelAsync(long id, ContentModel model)
        {
            if (model == null) throw new ArgumentNullException(nameof(model));
            
            var existing = await _context.ContentModels.FindAsync(id);
            if (existing == null) return;
            
            existing.Name = model.Name;
            existing.Description = model.Description;
            existing.IsActive = model.IsActive;
            existing.UpdatedAt = DateTime.UtcNow;
            
            await _context.SaveChangesAsync();
        }

        public async Task DeleteModelAsync(long id)
        {
            var model = await _context.ContentModels.FindAsync(id);
            if (model == null) return;
            
            _context.ContentModels.Remove(model);
            await _context.SaveChangesAsync();
        }

        public async Task<IEnumerable<Field>> GetFieldsAsync(long modelId)
        {
            var model = await _context.ContentModels.FindAsync(modelId);
            if (model == null) return new List<Field>();
            
            return string.IsNullOrEmpty(model.Fields) 
                ? new List<Field>() 
                : JsonSerializer.Deserialize<List<Field>>(model.Fields) ?? new List<Field>();
        }

        public async Task AddFieldAsync(long modelId, Field field)
        {
            if (field == null) throw new ArgumentNullException(nameof(field));
            
            var model = await _context.ContentModels.FindAsync(modelId);
            if (model == null) throw new InvalidOperationException($"Content model with ID {modelId} not found.");
            
            var fields = string.IsNullOrEmpty(model.Fields) 
                ? new List<Field>() 
                : JsonSerializer.Deserialize<List<Field>>(model.Fields) ?? new List<Field>();
            
            field.Id = fields.Count > 0 ? fields.Max(f => f.Id) + 1 : 1;
            field.CreatedAt = DateTime.UtcNow;
            field.UpdatedAt = DateTime.UtcNow;
            fields.Add(field);
            
            model.Fields = JsonSerializer.Serialize(fields);
            model.UpdatedAt = DateTime.UtcNow;
            
            await _context.SaveChangesAsync();
        }

        public async Task UpdateFieldAsync(long modelId, long fieldId, Field field)
        {
            if (field == null) throw new ArgumentNullException(nameof(field));
            
            var model = await _context.ContentModels.FindAsync(modelId);
            if (model == null) return;
            
            var fields = string.IsNullOrEmpty(model.Fields) 
                ? new List<Field>() 
                : JsonSerializer.Deserialize<List<Field>>(model.Fields) ?? new List<Field>();
            
            var existingField = fields.FirstOrDefault(f => f.Id == fieldId);
            if (existingField == null) return;
            
            existingField.Name = field.Name;
            existingField.Type = field.Type;
            existingField.IsRequired = field.IsRequired;
            existingField.Description = field.Description;
            existingField.Order = field.Order;
            existingField.UpdatedAt = DateTime.UtcNow;
            
            model.Fields = JsonSerializer.Serialize(fields);
            model.UpdatedAt = DateTime.UtcNow;
            
            await _context.SaveChangesAsync();
        }

        public async Task DeleteFieldAsync(long modelId, long fieldId)
        {
            var model = await _context.ContentModels.FindAsync(modelId);
            if (model == null) return;
            
            var fields = string.IsNullOrEmpty(model.Fields) 
                ? new List<Field>() 
                : JsonSerializer.Deserialize<List<Field>>(model.Fields) ?? new List<Field>();
            
            var fieldToRemove = fields.FirstOrDefault(f => f.Id == fieldId);
            if (fieldToRemove == null) return;
            
            fields.Remove(fieldToRemove);
            
            model.Fields = JsonSerializer.Serialize(fields);
            model.UpdatedAt = DateTime.UtcNow;
            
            await _context.SaveChangesAsync();
        }

        public async Task<IEnumerable<ContentItem>> GetItemsAsync(long modelId, int page = 1, int limit = 10)
        {
            return await _context.ContentItems
                .Include(i => i.Model)
                .Where(i => i.ModelId == modelId)
                .OrderByDescending(i => i.CreatedAt)
                .Skip((page - 1) * limit)
                .Take(limit)
                .ToListAsync();
        }

        public async Task CreateItemAsync(long modelId, ContentItem item)
        {
            if (item == null) throw new ArgumentNullException(nameof(item));
            
            item.ModelId = modelId;
            item.CreatedAt = DateTime.UtcNow;
            item.UpdatedAt = DateTime.UtcNow;
            
            _context.ContentItems.Add(item);
            await _context.SaveChangesAsync();
        }

        public async Task<ContentItem?> GetItemByIdAsync(long modelId, long itemId)
        {
            return await _context.ContentItems
                .Include(i => i.Model)
                .FirstOrDefaultAsync(i => i.Id == itemId && i.ModelId == modelId);
        }

        public async Task UpdateItemAsync(long modelId, long itemId, ContentItem item)
        {
            if (item == null) throw new ArgumentNullException(nameof(item));
            
            var existing = await _context.ContentItems
                .FirstOrDefaultAsync(i => i.Id == itemId && i.ModelId == modelId);
            if (existing == null) return;
            
            existing.Title = item.Title;
            existing.Data = item.Data;
            existing.Status = item.Status;
            existing.UpdatedAt = DateTime.UtcNow;
            
            await _context.SaveChangesAsync();
        }

        public async Task DeleteItemAsync(long modelId, long itemId)
        {
            var item = await _context.ContentItems
                .FirstOrDefaultAsync(i => i.Id == itemId && i.ModelId == modelId);
            if (item == null) return;
            
            _context.ContentItems.Remove(item);
            await _context.SaveChangesAsync();
        }

        public async Task BatchUpdateItemStatusAsync(List<long> itemIds, string status)
        {
            var items = await _context.ContentItems
                .Where(i => itemIds.Contains(i.Id))
                .ToListAsync();
                
            foreach (var item in items)
            {
                item.Status = status;
            }
            
            await _context.SaveChangesAsync();
        }

        // 重载方法：支持long类型的modelId和itemIds
        public async Task BatchUpdateItemStatusAsync(long modelId, List<long> itemIds, string status)
        {
            var intItemIds = itemIds.Select(id => (long)id).ToList();
            var items = await _context.ContentItems
                .Where(i => intItemIds.Contains(i.Id) && i.ModelId == modelId)
                .ToListAsync();
                
            foreach (var item in items)
            {
                item.Status = status;
            }
            
            await _context.SaveChangesAsync();
        }

        public async Task<int> GetItemsCountAsync(int? modelId = null, string? status = null)
        {
            var query = _context.ContentItems.AsQueryable();
            
            if (modelId.HasValue)
                query = query.Where(i => i.ModelId == modelId.Value);
                
            if (!string.IsNullOrEmpty(status))
                query = query.Where(i => i.Status == status);
                
            return await query.CountAsync();
        }

        // 重载方法：支持long类型的modelId
        public async Task<int> GetItemsCountAsync(long modelId, string? status = null)
        {
            var query = _context.ContentItems
                .Where(i => i.ModelId == modelId);
                
            if (!string.IsNullOrEmpty(status))
                query = query.Where(i => i.Status == status);
                
            return await query.CountAsync();
        }

        public async Task<List<ContentItem>> GetItemsByStatusAsync(string status, int? modelId = null, int skip = 0, int take = 20)
        {
            var query = _context.ContentItems
                .Where(i => i.Status == status);
                
            if (modelId.HasValue)
                query = query.Where(i => i.ModelId == modelId.Value);
                
            return await query
                .OrderByDescending(i => i.CreatedAt)
                .Skip(skip)
                .Take(take)
                .ToListAsync();
        }

        // 重载方法：支持long类型的modelId
        public async Task<List<ContentItem>> GetItemsByStatusAsync(long modelId, string status, int skip = 0, int take = 20)
        {
            return await _context.ContentItems
                .Where(i => i.ModelId == modelId && i.Status == status)
                .OrderByDescending(i => i.CreatedAt)
                .Skip(skip)
                .Take(take)
                .ToListAsync();
        }
    }
}